Skip to content

geotiff: honour ModelTiepointTag when ModelPixelScaleTag is absent (#1750)#1760

Open
brendancol wants to merge 1 commit into
mainfrom
issue-1750
Open

geotiff: honour ModelTiepointTag when ModelPixelScaleTag is absent (#1750)#1760
brendancol wants to merge 1 commit into
mainfrom
issue-1750

Conversation

@brendancol
Copy link
Copy Markdown
Contributor

Summary

  • _extract_transform() returned a default GeoTransform() with origin (0, 0) and has_georef=True whenever a TIFF carried ModelTiepointTag but no ModelPixelScaleTag, silently dropping the tiepoint's real-world X / Y. Downstream coordinate construction then placed the raster at (0, 0) with no warning.
  • Use the tiepoint X / Y to compute the origin (matching the tiepoint-with-scale branch) and fall back to the GeoTIFF spec convention of unit pixel scale (1.0, -1.0) when ModelPixelScaleTag is absent.
  • Considered returning has_georef=False instead. Rejected because the tiepoint encodes a real model X / Y; flagging the raster as ungeoreferenced would still mislabel it.

Closes #1750.

Test plan

  • New TestTiepointWithoutScale_1750 in xrspatial/geotiff/tests/test_geotags.py builds a TIFF with ModelTiepointTag only, asserts the extracted origin equals tp_x / tp_y and that pixel scale falls back to (1.0, -1.0). Covers both tp_i=tp_j=0 and non-zero tp_i / tp_j cases.
  • Confirmed the new tests fail on main (origin_x = 0.0 vs expected tiepoint X) and pass with the fix.
  • Existing xrspatial/geotiff/tests/ suite delta is identical to main; pre-existing GPU / matplotlib failures are unrelated to this change.

…1750)

`_extract_transform` previously returned the default `GeoTransform()`
(origin (0, 0), unit pixel size) with `has_georef=True` whenever a
ModelTiepointTag was present but ModelPixelScaleTag was missing. The
tiepoint's tp_x / tp_y values were silently dropped, so any downstream
code trusting `has_georef` constructed coordinates from origin (0, 0)
and relocated the raster.

Use the tiepoint's X / Y to build the origin (matching the
tiepoint-with-scale branch) and fall back to the spec-documented unit
pixel scale (1.0, -1.0). The alternative of returning has_georef=False
would still mislabel the raster as having no georeferencing even though
a real model X / Y is encoded in the tiepoint.

Added `TestTiepointWithoutScale_1750` in test_geotags.py with a helper
that emits a TIFF carrying ModelTiepointTag but no ModelPixelScaleTag.
Verified the new tests fail on main (origin_x = 0.0 instead of the
tiepoint X) and pass with the fix.

Closes #1750.
@github-actions github-actions Bot added the performance PR touches performance-sensitive code label May 12, 2026
@brendancol brendancol requested a review from Copilot May 12, 2026 23:50
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes GeoTIFF georeferencing extraction for TIFFs that include ModelTiepointTag but omit ModelPixelScaleTag, ensuring the tiepoint’s model-space X/Y is honored instead of silently defaulting to an origin at (0, 0) while still claiming the raster is georeferenced.

Changes:

  • Update _extract_transform() to compute origin from ModelTiepointTag even when ModelPixelScaleTag is missing, using a unit-scale fallback.
  • Add regression tests that build a minimal TIFF containing only ModelTiepointTag and validate the extracted origin and fallback pixel size behavior.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
xrspatial/geotiff/_geotags.py Adjust tiepoint-only transform extraction to preserve the tiepoint-defined origin and apply a unit pixel-scale fallback.
xrspatial/geotiff/tests/test_geotags.py Add regression tests and a minimal TIFF builder to validate tiepoint-only georeferencing behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +263 to +264
real-world (X, Y) origin for pixel (I, J) and the pixel scale defaults
to (1.0, 1.0).
Comment on lines +466 to +470
# Tiepoint without scale: honour the tiepoint origin and fall back to
# unit pixel size. Per the GeoTIFF spec a ModelTiepointTag encodes a
# real-world (X, Y) for pixel (I, J); dropping it would silently relocate
# the raster to (0, 0). Unit scale (1.0, -1.0) is the documented fallback
# when ModelPixelScaleTag is absent.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

performance PR touches performance-sensitive code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

geotiff: tiepoint-only georef silently drops origin (reports has_georef=True at 0,0)

2 participants